package com.edu.buservice.web.controller.Interceptor;

import cn.dev33.satoken.exception.*;
import com.edu.buservice.util.model.R;
import com.edu.buservice.util.model.enums.ErrorCodeEnum;
import com.edu.buservice.util.model.error.BizException;
import jakarta.validation.ConstraintViolationException;
import jakarta.validation.ValidationException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageConversionException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;

/**
 * @program: KQAIA
 * @description:
 * @author: 无恙
 * @create: 2025-02-09 19:42
 **/

@ControllerAdvice
@Slf4j
@ResponseBody
public class GlobalExceptionHandler {

	@ExceptionHandler(value = {BindException.class, ValidationException.class, MethodArgumentNotValidException.class})
	public R<List<String>> handleValidatedException(Exception e) {
		String msg = "";
		if (e instanceof MethodArgumentNotValidException) {
			MethodArgumentNotValidException ex = (MethodArgumentNotValidException) e;
			msg = ex.getBindingResult().getAllErrors().stream().findFirst().get().getDefaultMessage();
		} else if (e instanceof ConstraintViolationException) {
			ConstraintViolationException ex = (ConstraintViolationException) e;
			msg = ex.getConstraintViolations().stream().findFirst().get().getMessage();
		} else if (e instanceof BindException) {
			BindException ex = (BindException) e;
			msg = ex.getAllErrors().stream().findFirst().get().getDefaultMessage();
		}
		return R.fail(ErrorCodeEnum.PARAM_ERROR, msg);
	}

	@ExceptionHandler(HttpMessageConversionException.class)
	public R<?>  handleHttpMessageConversionException(HttpMessageConversionException e) {

		return R.fail(ErrorCodeEnum.PARAM_FORMAT_INVALID, e.getMessage());
	}

	@ExceptionHandler(value = {BizException.class})
	public R<List<String>> handleServiceException(BizException e) {
		return R.fail(e.getCode(), e.getMessage());
	}


	@ExceptionHandler(value = {NotLoginException.class})
	public R<String> handlerNotLoginException(NotLoginException nle) {
		// 不同异常返回不同状态码
		String message = "";
		if (nle.getType().equals(NotLoginException.NOT_TOKEN)) {
			message = "未提供Token";
		} else if (nle.getType().equals(NotLoginException.INVALID_TOKEN)) {
			message = "未提供有效的Token";
		} else if (nle.getType().equals(NotLoginException.TOKEN_TIMEOUT)) {
			message = "登录信息已过期，请重新登录";
		} else if (nle.getType().equals(NotLoginException.BE_REPLACED)) {
			message = "您的账户已在另一台设备上登录，如非本人操作，请立即修改密码";
		} else if (nle.getType().equals(NotLoginException.KICK_OUT)) {
			message = "已被系统强制下线";
		} else {
			message = "当前会话未登录";
		}
		// 返回给前端
		nle.printStackTrace();
		return R.fail(ErrorCodeEnum.AUTH_ERROR, message);
	}

	@ExceptionHandler(value = {NotRoleException.class, NotPermissionException.class})
	public R<String> handlerNotRoleException(Exception e) {
		String message = "";
		if (e instanceof NotRoleException) {
			message = "无此角色：" + ((NotRoleException) e).getRole();
		} else if (e instanceof NotPermissionException) {
			message = "无此权限：" + ((NotPermissionException) e).getCode();
		}
		return R.fail(ErrorCodeEnum.ACCESS_DENIED, message);
	}


	@ExceptionHandler(value = {DisableServiceException.class})
	public R<String> handlerDisableLoginException(DisableServiceException e) {
		return R.fail(ErrorCodeEnum.ACCOUNT_LOCKED, "账户被封禁：" + e.getDisableTime() + "秒后解封");
	}

	@ExceptionHandler(value = {NotSafeException.class})
	public R<String> handlerNotSafeException(NotSafeException e) {
		return R.fail(ErrorCodeEnum.LOGIN_FAILED, "登录环境异常：" + e.getMessage());
	}

	@ExceptionHandler(value = {SaTokenException.class})
	public R<String> handlerSaTokenException(SaTokenException e) {
		return R.fail(ErrorCodeEnum.AUTH_ERROR, e.getMessage());
	}

	/**
	 * 处理所有的异常和Throwable类
	 * @param e
	 * @return
	 */
	@ExceptionHandler({Exception.class,Throwable.class})
	public R<String> ExceptionHandler(Exception e){
		log.error("全局异常捕获：",e);
		return R.fail(ErrorCodeEnum.SYSTEM_ERROR);
	}


}
